namespace SubSonic
{
    using SubSonic.Utilities;
    using System;
    using System.Collections.Generic;
    using System.Data;

    public class DB
    {
        private string _connectionString;
        private DataProvider _provider;
        private string _providerName;
        private List<StoredProcedure> _sps;
        private TableSchema.TableCollection _tables;
        private TableSchema.TableCollection _views;

        public DB(string providerName)
        {
            this.Tables = new TableSchema.TableCollection();
            this.Views = new TableSchema.TableCollection();
            this._tables.AddRange(DataService.GetTables(providerName));
            this._views.AddRange(DataService.GetViews(providerName));
            if (this._sps == null)
            {
                this.LoadStoredProcedures(providerName);
            }
        }

        private void LoadStoredProcedures(string providerName)
        {
            string[] sPList = DataService.GetSPList(providerName);
            if (sPList.Length > 0)
            {
                this._sps = new List<StoredProcedure>();
                DataProvider provider = DataService.Providers[providerName];
                foreach (string str in sPList)
                {
                    if (string.IsNullOrEmpty(provider.SPStartsWith) || str.StartsWith(provider.SPStartsWith))
                    {
                        StoredProcedure item = new StoredProcedure(str, provider);
                        IDataReader sPParams = DataService.GetSPParams(str, providerName);
                        while (sPParams.Read())
                        {
                            StoredProcedure.Parameter parameter = new StoredProcedure.Parameter();
                            parameter.DBType = DataService.GetDbType(sPParams["DataType"].ToString(), providerName);
                            if (Utility.IsMatch(sPParams["mode"].ToString(), "INOUT"))
                            {
                                parameter.Mode = ParameterDirection.InputOutput;
                            }
                            parameter.Name = sPParams["Name"].ToString();
                            parameter.QueryParameter = provider.MakeParam(parameter.Name);
                            parameter.DisplayName = Utility.GetParameterName(parameter.Name, provider);
                            item.Parameters.Add(parameter);
                        }
                        sPParams.Close();
                        this._sps.Add(item);
                    }
                }
            }
        }

        public string ConnectionString
        {
            get
            {
                return this._connectionString;
            }
            set
            {
                this._connectionString = value;
            }
        }

        public DataProvider Provider
        {
            get
            {
                return this._provider;
            }
            set
            {
                this._provider = value;
            }
        }

        public string ProviderName
        {
            get
            {
                return this._providerName;
            }
            set
            {
                this._providerName = value;
            }
        }

        public List<StoredProcedure> StoredProcedures
        {
            get
            {
                if (this._sps == null)
                {
                    this.LoadStoredProcedures(this.ProviderName);
                }
                return this._sps;
            }
            set
            {
                this._sps = value;
            }
        }

        public TableSchema.TableCollection Tables
        {
            get
            {
                return this._tables;
            }
            set
            {
                this._tables = value;
            }
        }

        public TableSchema.TableCollection Views
        {
            get
            {
                return this._views;
            }
            set
            {
                this._views = value;
            }
        }
    }
}

